﻿#region Using Directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Timers;
using System.Threading;
using System.Net;
using System.Drawing.Drawing2D;
using System.Xml;
using System.Management;
#endregion

namespace CameraRecorder
{
    public partial class F_Main : Form
    {
        #region Constructor
        public F_Main()
        {
            InitializeComponent();

            //set window and timer
            this.StartPosition = FormStartPosition.CenterScreen;
            T_timer.Interval = intervalTimer;
        } 
        #endregion

        #region Member Variables
        string statusLabel = string.Empty;
        string pathSaveCapture = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        string sourceURL = string.Empty;
        string userName = string.Empty;
        string password = string.Empty;
        bool saveCapture = false;
        bool requireLogon = false;
        int intervalTimer = 100; //10 fra/sec
        bool allowConnection = false;
        #endregion

        #region Form Events
        private void TSMI_connect_Click(object sender, EventArgs e)
        {
            CameraConnect();
        }

        private void CameraConnect()
        {
            if (!string.IsNullOrEmpty(sourceURL))
            {
                allowConnection = true;
                T_timer.Start();
            }
            else
            {
                CameraCloseConnection();
                MessageBox.Show("SourceUrl is empty, please first configure camera!",
                                "Waring",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Warning);
            }
        }

        private void TSMI_cameraSettings_Click(object sender, EventArgs e)
        {
            CameraCloseConnection();
            F_CameraSettings fSettings = new F_CameraSettings();

            //load date from xml file
            fSettings.SourceURL = sourceURL;
            fSettings.RequireLogon = requireLogon;
            fSettings.UserName = userName;
            fSettings.Password = password;
            fSettings.SaveCapture = saveCapture;
            fSettings.PathSaveCapture = pathSaveCapture;
            fSettings.FrameInterval = intervalTimer;

            //show configure window            
            fSettings.ShowDialog();
            if (fSettings.DialogResult == DialogResult.OK)
            {
                sourceURL = fSettings.SourceURL;
                T_timer.Interval = fSettings.FrameInterval;
                if (fSettings.RequireLogon)
                {
                    requireLogon = true;
                    userName = fSettings.UserName;
                    password = fSettings.Password;
                }
                else
                {
                    requireLogon = false;
                }
                if (fSettings.SaveCapture)
                {
                    saveCapture = true;
                    pathSaveCapture = fSettings.PathSaveCapture;
                }
                else
                {
                    saveCapture = false;
                }
            }
        }

        private void TSMI_disconnect_Click(object sender, EventArgs e)
        {
            CameraCloseConnection();
        }

        private void F_Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            CameraCloseConnection();
        }

        private void BW_work_DoWork(object sender, DoWorkEventArgs e)
        {
            PB_view.Image = CameraReadBmp();
            statusLabel = "Refresh date: " + DateTime.Now.ToString();
        }

        private void T_timer_Tick(object sender, EventArgs e)
        {
            T_timer.Stop();
            if (allowConnection)
            {
                BW_work.RunWorkerAsync();
            }
        }

        private void BW_work_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (allowConnection)
            {
                PB_view.Refresh();
                TSSL_statusLabel.Text = statusLabel;
                T_timer.Start(); 
            }
            else
            {
                PB_view.Image = null;
                PB_view.Refresh();
            }
        }

        private void TSMI_exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void TSMI_aboutProgram_Click(object sender, EventArgs e)
        {
            F_AboutProgram fAbout = new F_AboutProgram();
            fAbout.ShowDialog();
        }

        private void F_Main_Load(object sender, EventArgs e)
        {
            string xmlFile = "cameraSettings.xml";
            if (File.Exists(xmlFile))
            {
                XmlTextReader reader = new XmlTextReader(xmlFile);
                while (reader.Read())
                {
                    XmlNodeType nType = reader.NodeType;
                    if (nType == XmlNodeType.Element)
                    {
                        if (reader.Name == "SourceURL")
                        {
                            sourceURL = reader.NamespaceURI;
                        }
                        if (reader.Name == "FramePerMinute")
                        {
                            intervalTimer = int.Parse(reader.NamespaceURI);
                        }
                        if (reader.Name == "RequireLogon")
                        {
                            requireLogon = bool.Parse(reader.NamespaceURI);
                        }
                        if (reader.Name == "UserName")
                        {
                            userName = reader.NamespaceURI;
                        }
                        if (reader.Name == "Password")
                        {
                            password = reader.NamespaceURI;
                        }
                        if (reader.Name == "SaveCapture")
                        {
                            saveCapture = bool.Parse(reader.NamespaceURI);
                        }
                        if (reader.Name == "PathSaveCapture")
                        {
                            pathSaveCapture = reader.NamespaceURI;
                        }
                    }
                }
                reader.Close();
            }
        }
        #endregion

        #region Functions
        private void CameraCloseConnection()
        {
            allowConnection = false;           
            TSSL_statusLabel.Text = "Connection closed";
        }

        private Bitmap CameraReadBmp()
        {
            Bitmap bmp = null;

            try
            {
                byte[] buffer = new byte[100000];
                int read, total = 0;

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(sourceURL);
                if (requireLogon)
                {
                    req.Credentials = new NetworkCredential(userName, password);
                }

                WebResponse resp = req.GetResponse();
                Stream stream = resp.GetResponseStream();

                while ((read = stream.Read(buffer, total, 1000)) != 0)
                {
                    total += read;
                }

                bmp = (Bitmap)Bitmap.FromStream(
                      new MemoryStream(buffer, 0, total));

                Graphics g = Graphics.FromImage(bmp);
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                Brush blackBrush = new SolidBrush(Color.Black);
                g.FillRectangle(blackBrush, new Rectangle(2, 2, 285, 22));
                g.DrawString(DateTime.Now.ToString(), new Font("Courier New", 18, FontStyle.Bold), Brushes.White, new PointF(0, 0));
                Image image = (Image)bmp;
                Size size = new Size(bmp.Width, bmp.Height);
                Bitmap b = new Bitmap(image, size);
                bmp = b;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error read image from camera\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                CameraCloseConnection();
            }

            if (saveCapture)
            {
                //if setting file is jpeg then
                CameraSaveCapture(OutputCaptureFormat.Jpeg, bmp);
            }

            return bmp;
        }      

        private void CameraSaveCapture(OutputCaptureFormat outRec, Bitmap bmp)
        {
            switch (outRec)
	        {
                //save to bitmap file (jpeg)
                case OutputCaptureFormat.Jpeg:
                    {
                        //check free disc
                        string discChar = pathSaveCapture.Substring(0, pathSaveCapture.IndexOf(":")).ToUpper();

                        ManagementObjectSearcher query1 = new
ManagementObjectSearcher("SELECT * FROM win32_logicaldisk");
                        ManagementObjectCollection queryCollection1 = query1.Get();
                        foreach (ManagementObject mo in queryCollection1)
                        {
                            string searchString = mo.Path.ToString();
                            searchString = searchString.Substring(searchString.LastIndexOf("="), searchString.Length - searchString.LastIndexOf("="));
                            searchString = searchString.Substring(2, 1);

                            if (discChar.ToUpper() == searchString)
                            {
                                ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"" + discChar + ":\"");
                                disk.Get();
                                ulong discSize = (ulong)disk["Size"];
                                ulong freeSpace = (ulong)disk["FreeSpace"];
                                if (freeSpace < (ulong)(discSize / 10))
                                {
//                                  //delete older file capture
                                    DirectoryInfo dInf = new DirectoryInfo(
pathSaveCapture);
                                    FileInfo[] fSysInfo = dInf.GetFiles();
                                    DateTime oldestFileTime = DateTime.Now;
                                    string oldestFileName = string.Empty;
                                    foreach (FileInfo oFile in fSysInfo)
                                    {
                                        if (oFile.CreationTime < oldestFileTime)
                                        {
                                            oldestFileTime = oFile.CreationTime;
                                            oldestFileName = oFile.FullName;
                                        }
                                    }
                                    File.Delete(oldestFileName);
                                    CameraSaveJpegProcess(bmp);
                                }
                                else
                                {
                                    //save process
                                    CameraSaveJpegProcess(bmp);
                                }
                            }
                        }                     
                        break;
                    }
                default:
                    break;
	        }
        }

        private void CameraSaveJpegProcess(Bitmap bmp)
        {
            //unique idetificator
            DateTime dateTime = DateTime.Now;
            string sDateTime = dateTime.ToString();
            sDateTime = sDateTime.Replace(":", "_");

            string path = pathSaveCapture + "\\out_" + sDateTime + ".jpg";

            //if exist file, delete him
            if (File.Exists(path))
            {
                File.Delete(path);
            }

            //save to file
            try
            {
                bmp.Save(path,
                         System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error 01 - Save capture to image\n" +
                                ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion         
    }

    public enum OutputCaptureFormat
	{
        Jpeg
	} 
}
